package com.oauth.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.token.TokenService;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;

import javax.sql.DataSource;
import java.util.concurrent.TimeUnit;


@Configuration
@EnableAuthorizationServer
public class OAuthConfig extends AuthorizationServerConfigurerAdapter {

    /**
     * spring 密码加密
     */
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private DataSource dataSource;

    @Autowired
    private UserDetailsService userDetailsService;

//    @Autowired
//    @Qualifier("customClientDetailsService")
//    private ClientDetailsService clientDetailsService;

//    @Autowired
//    private AuthorizationServerTokenServices tokenService;



//    @Autowired
//    private AuthorizationServerTokenServices serverTokenServices;

    /**
     * 作用：存取token的,默认是内存的实现，改为jdbc实现
     * @return
     */
    @Bean
    public TokenStore tokenStore(){
        JdbcTokenStore jdbcTokenStore = new JdbcTokenStore(dataSource);
        return jdbcTokenStore;
    }

//    @Bean
//    @Primary
//    public DefaultTokenServices tokenServices(){
//        DefaultTokenServices tokenServices=new DefaultTokenServices();
//        tokenServices.setAuthenticationManager(authenticationManager);
//        tokenServices.setTokenStore(tokenStore());
//        tokenServices.setSupportRefreshToken(true);
//        tokenServices.setClientDetailsService(new JdbcClientDetailsService(dataSource));
//        return tokenServices;
//    }


    /**
     * AuthenticationManager--传入用户信息是不是合法的
     * 认证服务器
     * @param endpoints
     * @throws Exception
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
                .tokenStore(tokenStore())//使tokenStore生效
                .userDetailsService(userDetailsService)
//                .reuseRefreshTokens(true)
//                .tokenServices(tokenServices())
                .authenticationManager(authenticationManager);
//                .setClientDetailsService(clientDetailsService());
//                .authenticationManager(authenticationManager);
//        tokenServices.setTokenStore(tokenStore());




////        tokenServices.setClientDetailsService(endpoints.getClientDetailsService());
////        tokenServices.setTokenEnhancer(endpoints.getTokenEnhancer());
////        tokenServices.setAccessTokenValiditySeconds((int) TimeUnit.DAYS.toSeconds(30)); // 30天
//        endpoints.tokenServices(tokenServices);
    }


//    /**
//     * 授权--内存
//     * ClientDetailsServiceConfigurer客户端详情配置
//     * @param clients
//     * @throws Exception
//     */
//    @Override
//    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
//        clients.inMemory()
//                .withClient("orderApp")//指明应用client-id
//                .secret(passwordEncoder.encode("123456"))//应用密码
//                .scopes("read","write")//ACL权限控制
//                .accessTokenValiditySeconds(10)//发出去的令盘有效期是多少秒
//                .resourceIds("order-service")//资源服务器ID，可以多个
//                .authorizedGrantTypes("password")//授权方式，支持4种授权方式
//                .refreshTokenValiditySeconds(3600)
//                .and()
//                .withClient("orderService")//指明应用client-id
//                .secret(passwordEncoder.encode("123456"))//应用密码
//                .scopes("read")//ACL权限控制
//                .accessTokenValiditySeconds(3600)//发出去的令盘有效期是多少秒
//                .resourceIds("order-service")//资源服务器ID，可以多个
//                .authorizedGrantTypes("password");//授权方式，支持4种授权方式
//
//    }

    /**
     * 授权--数据库，去数据库查找oauth_details_client
     * ClientDetailsServiceConfigurer客户端详情配置
     * @param clients
     * @throws Exception
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.jdbc(dataSource);
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.checkTokenAccess("isAuthenticated()");//配置用于访问token的检查规则
    }
}
